/*******************************************************************************
** Imputacion.h: contiene todo lo necesario para trabajar con la solapa
**                   Imputacion.
**
** author: M-S Hernández-García
**
**  This file is part of TEIDE2.
**
**  TEIDE2 is free software: you can redistribute it and/or modify
**  it under the terms of the GNU General Public License as published by
**  the Free Software Foundation, either version 3 of the License, or
**  (at your option) any later version.
**
**  Foobar is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**  GNU General Public License for more details.
**
**  You should have received a copy of the GNU General Public License
**  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
**
*******************************************************************************/

#ifndef IMPUTACION_H
#define IMPUTACION_H

#include <QVariant>
#include <QAction>
#include <QApplication>
#include <QButtonGroup>
#include <QComboBox>
#include <QFrame>
#include <QLabel>
#include <QLineEdit>
#include <QProgressBar>
#include <QPushButton>
#include <QWidget>
#include <QMenu>
#include <QTableView>
#include <QItemSelectionModel>
#include <QProgressDialog>
#include <QScrollArea>
#include "TablaModelI.h"
#include "Test.h"
#include "Opciones.h"
#include "CambiarMicrodato.h"
#include "EntradaDatos.h"
#include "TareasComunes.h"
#include <time.h>
#include <stdlib.h>

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class TipoNodoCC {
public:
  unsigned nodo;
  unsigned distancia;

  bool operator < (const TipoNodoCC & c)
     { return distancia < c.distancia; }

  bool operator == (const TipoNodoCC & c)
     { return false; }
};



/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


class TFmeImputacion : public QWidget
{
    Q_OBJECT

public:

    QLineEdit *PanProgreso;
    QLabel *LabOperacion;
    QLabel *LabProgreso;
    QLabel *LabPorcentaje;
    QLabel *LabElemento;
    QLineEdit *EdtOperacion;
    QProgressBar *PbrProgreso;
    QLineEdit *EdtPorcentaje;
    QLineEdit *EdtElemento;
    QFrame *PanContenedor;
    QFrame *PanIrA;
    QFrame *PanIrA2;
    QLabel *LabIrARegistroPorNumero;
    QLabel *LabIrAVariablePorNombre;
    QLabel *LabIrARegistroPorNombre;
    QLabel *LabMicroDatoOriginal;
    QLabel *LabNumVariablesAImputarBasico;
    QLabel *LabNumVariablesAImputar;
    QLabel *LabNumVariablesImputadas;
    QLabel *LabIrAVariablePorNumero;
    QLineEdit *EdtIrARegistroPorNumero;
    QComboBox *CbxIrAVariablePorNombre;
    QComboBox *CbxIrARegistroPorNombre;
    QLineEdit *EdtMicroDatoOriginal;
    QLineEdit *EdtNumVariablesAImputarBasico;
    QLineEdit *EdtNumVariablesAImputar;
    QLineEdit *EdtNumVariablesImputadas;
    QLineEdit *EdtIrAVariablePorNumero;
    QFrame *PanRegistroDonante;
    QLabel *LabNumRegistrosDonantes;
    QLabel *LabNavRegDonantes;
    QLabel *LabDistanciaAlfa;
    QPushButton *UpdRegistroDonante_sig;
    QPushButton *UpdRegistroDonante_ant;
    QLineEdit *EdtDistancia;
    QPushButton *ButCambiarRegistroDonante;
    QLineEdit *EdtMensajeRegistroDonante;
    QLineEdit *EdtIndiceRegistroDonante;

    MiTabla *view;   // vista de la tabla principal
    MiTabla *view2;  // vista de la tabla variables
    MiTabla *view3;  // vista de la tabla registros

    QFrame *SbrBarraEstado;
    QFrame *SbrBarraEstado1;
    QLabel *LabBarraEstado1;
    QFrame *SbrBarraEstado2;
    QLabel *LabBarraEstado2;
    QFrame *PanLeyenda;
    QLabel *ShpMicroDatoSimImputar;
    QLabel *LabMicroDatoSinImputar;
    QLabel *ShpMicroDatoImputado;
    QLabel *LabMicroDatoImputado;
    QLabel *ShpRegistroDonante;
    QLabel *LabRegistroDonante;
    QLabel *ShpRegistroExcluido;
    QLabel *LabRegistroExcluido;
    QLabel *ShpRegistroIncorrecto;
    QLabel *LabRegistroIncorrecto;
    QLabel *ShpMicroDatoSimImputarIncorrecto;
    QLabel *LabMicroDatoSinImputarIncorrecto;
    QSqlDatabase *AdqConsulta;
    QMenu * menu;
    QMenu * menu2;
    QComboBox *VisualizarReg;
    QScrollArea *scrollArea1;

    TFmeImputacion(QWidget* parent, const char* name, Qt::WindowFlags fl, QSqlDatabase *AdcConexionBD, TFmeTest *FmeTestAsociado, TFrmIrAVariable *FrmIrAVariable, TFrmCambiarMicrodato *FrmCambiarMicrodato, TFrmOpciones *FrmOpciones, bool oracle, bool Xml, QString NombreBaseDatos, bool excel, QTabWidget *PctContenedorPrincipal, QStringList *ListaIds);
    void ajustarSize();
    QPushButton *GetButCambiarRegistroDonante();
    TFmeTest *GetTestAsociado();
    unsigned GetRegistroDonante(unsigned IndiceRegistro);
    double *GetRegistro(unsigned IndiceRegistro);
    double GetValor(unsigned IndiceRegistro, unsigned IndiceVariable);
    unsigned GetNumRegistrosDonantes();
    unsigned GetNumRegistrosExcluidos();
    unsigned GetNumRegistrosCorrectos();
    unsigned GetNumRegistrosIncorrectos();
    unsigned GetNumRegistrosWarning();
    unsigned GetNumRegistrosACorregir();
    double GetPorcentajeRegistrosDonantes();
    double GetPorcentajeRegistrosExcluidos();
    double GetPorcentajeRegistrosCorrectos();
    double GetPorcentajeRegistrosIncorrectos();
    double GetPorcentajeRegistrosWarning();
    double GetPorcentajeRegistrosACorregir();
    double GetTiempoProcesoSegundos();
    double GetTiempoProcesoMilisegundos();
    unsigned GetNumVariablesRangoAImputar(unsigned IndiceRegistro);
    unsigned GetNumVariablesEditsAImputar(unsigned IndiceRegistro);
    unsigned GetNumVariablesRangoAImputarImputables(unsigned IndiceRegistro);
    unsigned GetNumVariablesEditsAImputarImputables(unsigned IndiceRegistro);
    unsigned GetNumVariablesExtendidasAImputar(unsigned IndiceRegistro);
    unsigned GetNumVariablesExtendidasAImputarLargo(unsigned IndiceRegistro);
    unsigned GetNumVariablesImputadas(unsigned IndiceRegistro);
    unsigned GetNumRegistrosImputados(unsigned IndiceVariable);
    double GetPorcentajeRegistrosImputados(unsigned IndiceVariable);
    double **GetMatrizMicroDatos();
    double GetPromedioVariablesImputadasTotal();
    double GetPromedioVariablesImputadasSinWarning();
    unsigned GetIndiceVariableEnPosicion(unsigned Posicion);
    double GetPesoVariableEnPosicion(unsigned Posicion);
    double GetPromedioErroresRango();
    double GetPromedioErroresEdits();
    double GetPromedioErroresTotal();
    double GetPromedioSizeCompConexas();
    double GetPromedioDistancias();
    bool MicrodatoImputado(unsigned IndiceRegistro, unsigned IndiceVariable) ;
    bool RegistroExcluido(unsigned IndiceRegistro);
    bool RegistroIncorrecto(unsigned IndiceRegistro);
    bool RegistroWarning(unsigned IndiceRegistro);
    bool RegistroDonante(unsigned IndiceRegistro);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Asigna o devuelve del valor de PermImputacManual, el cual indica si se puede modificar manualmente.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void SetPermImputacManual(bool valor);
    bool GetPermImputacManual();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Salvar los microdatos en un fichero.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void SalvarMicrodatosEnFichero(QString NombreFichero);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Asociar las clases provenientes de etapas anteriores.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void AsociarClases(TFmeTest *FmeTestAsociado);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Actualizar la informacion del registro donante.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void ActualizarInformacionRegistroDonante(unsigned IndiceRegistro, unsigned PosicionRegistroDonante);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Buscar la siguiente variable con error hacia la derecha en registro incorrecto.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    unsigned BuscarVariableErrorDerechaRI(unsigned FilaOrigen, unsigned ColumnaOrigen);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Buscar la siguiente variable con error hacia la izquierda en registro incorrecto.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    unsigned BuscarVariableErrorIzquierdaRI(unsigned FilaOrigen, unsigned ColumnaOrigen);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Buscar el siguiente microdato erroneo hacia arriba en registro incorrecto.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    unsigned BuscarMicroDatoErrorArribaRI(unsigned FilaOrigen, unsigned ColumnaOrigen);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Buscar el siguiente microdato erroneo hacia abajo en registro incorrecto.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    unsigned BuscarMicroDatoErrorAbajoRI(unsigned FilaOrigen, unsigned ColumnaOrigen);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Buscar la siguiente variable con error hacia la derecha.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    unsigned BuscarVariableErrorDerecha(unsigned FilaOrigen, unsigned ColumnaOrigen);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Buscar la siguiente variable con error hacia la izquierda.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    unsigned BuscarVariableErrorIzquierda(unsigned FilaOrigen, unsigned ColumnaOrigen);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Buscar el siguiente microdato erroneo hacia arriba.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    unsigned BuscarMicroDatoErrorArriba(unsigned FilaOrigen, unsigned ColumnaOrigen);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Buscar el siguiente microdato erroneo hacia abajo.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    unsigned BuscarMicroDatoErrorAbajo(unsigned FilaOrigen, unsigned ColumnaOrigen);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Buscar la componente conexa a partir de una variable por una busqueda en profundidad.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void BuscarComponenteConexaDFS(unsigned IndiceVariable, bool *VariablesVisitadas, QList<TipoNodoCC> &ComponenteConexa);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Buscar la componente conexa a partir de una variable por una busqueda en anchura.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void BuscarComponenteConexaBFS(unsigned IndiceVariable, bool *VariablesVisitadas, list<TipoNodoCC> &ComponenteConexa);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Buscar una donacion correcta.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    TTipoImputacionRegistro BuscarDonacionCorrecta(unsigned IndiceRegistroAImputar, unsigned IndiceRegistroDonante, QSet<unsigned> VariablesRangoAImputar, QSet<unsigned> VariablesEditsAImputar, QSet<unsigned> VariablesExtendidasAImputar, QSet<unsigned> VariablesExtendidasLargasAImputar, double *RegistroTest, unsigned *NumVariablesImputadas);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CargarEnLista();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Realizar un chequeo de los filtros y los edits explicitos sobre un determinado registro objetivo.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    bool CheckRegistro(unsigned IndiceRegistroAImputar, double *RegistroTest, QSet<unsigned> VariablesModificadas);
    bool CheckRegistro2(unsigned IndiceRegistroAImputar, double *RegistroTest, QSet<unsigned> VariablesModificadas);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Realizar una enumeracion sobre el numero de variables del conjunto que se pase para probar si el registro se puede arreglar.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    bool CheckEnumeracion(QSet<unsigned> VariablesEnumeracion, unsigned NumVariablesEnumeracion, TipoPesoVariable *VectorPesosVariables, unsigned IndiceRegistroAImputar, double *RegistroTest, double *RegistroBackup, double *RegistroDonante, QSet<unsigned> VariablesModificadas);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Calcular las estadisticas de los procesos llevados a cabo.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CalcularEstadisticas();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copiar la rejilla desde los microdatos originales.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CopiarRejillaMicroDatos();
    void CopiarRejillaMicroDatos2();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copiar la rejilla de variable desde la rejilla de variable de microdatos originales.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CopiarRejillaVariable();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copiar la rejilla de registro desde la rejilla de variable de microdatos originales.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CopiarRejillaRegistroDonante();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Crear la matriz de microdatos.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CrearMatrizMicroDatos();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copiar la matriz de microdatos desde los originales.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CopiarMatrizMicroDatos();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Crear el conjunto de registros donantes.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CrearRegistrosDonantes();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Crear la matriz de tipo de imputacion.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CrearMatrizImputacion();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Crear el conjunto de registros incorrectos.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void InicializarConjuntoRegistrosIncorrectos();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Inicializar el conjunto de registros warning.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void InicializarConjuntoRegistrosWarning();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Crear el conjunto de variables a imputar.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CrearVariablesAImputar();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Obtener mensaje para mostrar en los registros incorrectos
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   void ObtenerInforRegIncorrecto(int registro);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Calcular la distancia de dos valores en dos registros distintos sobre una misma variable.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    double CalcularDistanciaEnVariable(unsigned IndiceVariable, double x1, double x2);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Crear la matriz de registros donantes.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CrearMatrizRegistrosDonantes();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Crear el conjunto de registros excluidos.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CrearConjuntoRegistrosExcluidos();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Crear el grafo de dependencias de variables.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CrearGrafoVariables();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Crear las componentes conexas del grafo de variables.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CrearComponentesConexas();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Crear el vector de pesos de variables.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CrearVectorPesosVariables();
    void ordenar();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Crear la matriz de tipos de variables a imputar.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CrearMatrizTiposVariablesAImputar();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Actualizar el registro.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CommitRegistro(unsigned IndiceRegistro, double *Registro);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copiar dos registros.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CopiarRegistros(double *RegistroOrigen, double *RegistroDestino);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Eliminar de los conjuntos a imputar las variables no imputables y las variables excluidas.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void EliminarVariablesNoImputables();
    void EliminarVariablesBasicasNoImputables();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Obtener el numero de variables en las que se diferencia el registro test de los valores originales.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    unsigned GetNumVariablesDistintas(unsigned IndiceRegistro, double *Registro);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Deshabilitar la informacion que describe al registro donante.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void DeshabilitarInformacionRegistroDonante();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Escribir mensaje de informacion en la barra de estado.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void EscribirInformacion();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Indica si un registro es donante o no.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    bool EvaluarRegistroConPatron(bool *Patron, unsigned *VectorIndices, double *RegistroTest, double *RegistroDonante, unsigned NumVariablesEnImputacion, unsigned IndiceRegistro, QSet<unsigned> VariablesModificadas);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Evaluar el registro despues de haber hecho una modificacion manual.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void EvaluarRegistroModificado(unsigned IndiceRegistro, unsigned IndiceVariable, double ValorNuevo);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Fijar la cantidad de datos que intervienen en el proceso.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void FijarCantidadDatos();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Genera las combinaciones de n sobre m.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void inic_Patron(bool *Patron, unsigned n);
    void inic_Patron(bool *Patron, unsigned n, unsigned inic);
    bool prueba(bool *Patron, unsigned *VectorIndices, double *RegistroTest, double *RegistroDonante, double *RegistroBackup, unsigned IndiceRegistro, unsigned n, unsigned m, unsigned k, unsigned t, QSet<unsigned> VariablesModificadas);
    bool GeneraNSobreM(bool *Patron, unsigned *VectorIndices, double *RegistroTest, double *RegistroDonante, double *RegistroBackup, unsigned IndiceRegistro, unsigned n, unsigned m, unsigned k, unsigned t, QSet<unsigned> VariablesModificadas);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Devolver la posicion que tiene una variable dentro del vector de aparicion en edit.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    unsigned GetPosicionPorIndiceVariable(unsigned IndiceVariable);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Devolver el map desde un vector.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    QMap<QString,double> *GetMapDesdeVector(double *Valores);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Habilitar la informacion que describe al registro donante.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void HabilitarInformacionRegistroDonante();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Fijar el ancho de las columnas de la rejilla principal.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void FijarAnchoColumnasRejilla(unsigned ancho);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Inicializar estructuras de imputacion.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void InicializarEstructurasImputacion();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Imputar los microdatos asociados mediante la tecnica de registro donante.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void ImputarMicroDatosRegistroDonante();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Imputar los microdatos asociados mediante la tecnica de ecuacion de regresion lineal multiple (ERLM).
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void ImputarMicroDatosERLM();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Imputar el conjunto de variables sobre el registro test.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void ImputarVariablesTest(QSet<unsigned> VariablesAImputar, double *RegistroTest, double *RegistroBackup, double *RegistroDonante, QSet<unsigned> *VariablesModificadas);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Inicializar la matriz de tipo de imputacion.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void InicializarMatrizImputacion();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Inicializar los vectores de las variables a imputar.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void InicializarVariablesAImputar();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Inicializar el vector de numero de variables imputadas.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void InicializarNumVariablesImputadas();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Inicializar el vector de numero de registros imputados.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void InicializarNumRegistrosImputados();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Inicializar la matriz de registros donantes.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void InicializarMatrizRegistrosDonantes();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Inicializar el sistema de progreso.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void InicSistemaProgreso(QString Operacion, unsigned NumElementos);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Incrementar el sistema de progreso.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void IncSistemaProgreso();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Mostrar la informacion asociada a la fila y a la columna.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void MostrarInfoAsociada(unsigned Fila, unsigned Columna, bool Fijar);
    void MostrarInfoAsociada(unsigned Fila, unsigned Columna, unsigned numreg, bool Fijar);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Pinta la rejilla registro.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void repintarRegistroDonante(int col);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Funcion de ordenacion de las variables a traves de su peso.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    int OrdenacionPesosVariablesAscendente(const void *A, const void *B);    
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Calcular la media del vector de entrada.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    double CalcularMedia(double *v, unsigned n);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Calcular la mediana del vector de entrada.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    double CalcularMediana(double *v, unsigned n);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Calcular la media recortada del vector de entrada.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    double CalcularMediaR(double *v, unsigned n, unsigned rec);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Calcular la moda del vector de entrada.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    double CalcularModa(double *v, unsigned n);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Restaurar el registro actual con la copia.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void RestaurarRegistro(double *RegistroOrigen, double *RegistroBackup);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Restaurar el registro actual con la copia.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void RestaurarRegistro(unsigned IndiceRegistro);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Sustituir los valores imputados en las variables numericas por otros valores temporales.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void RestaurarEstadisticas(int registro, bool warning);
    void SustituirImputacionVariablesNumericas();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Salvar los microdatos en la base de datos.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void SalvarMicrodatosEnBBDD(QString NombreBaseTablaSalida);
    QString SustCaracter(QString Cadena, char CarABuscar, char CarSustitucion);
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Repintar la Rejilla principal.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void repintar();

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void ImputarMicroDatoRegistroDonante(int registro, int IndiceRegistroDonante);

    TTipoImputacionRegistro BuscarDonacionCorrecta2(unsigned IndiceRegistroAImputar, unsigned IndiceRegistroDonante, QSet<unsigned> VariablesRangoAImputar, QSet<unsigned> VariablesEditsAImputar, QSet<unsigned> VariablesExtendidasAImputar, QSet<unsigned> VariablesExtendidasLargasAImputar, double *RegistroTest, unsigned *NumVariablesImputadas);

    void DesImputarMicroDatoRegistroDonante(int registro) ;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    QComboBox *GetVisualizarReg();    
    void cargarmodelo4(QString exp);
    void cargarmodelo1(unsigned numreg, QSet<unsigned> ConjuntoRegistros);
    void cargarmodelo23(unsigned numreg, QSet<unsigned> ConjuntoRegistros);

public slots:

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PULSAR EL BOTON DE IMPUTAR.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void ButCambiarRegistroDonanteClick();

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SELECCIONAR UNA VARIABLE DE LA LISTA DE IR A VARIABLES.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void CbxIrAVariablePorNombreCloseUp(int index);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PULSAR UNA TECLA EN EL EDIT DE IR A REGISTRO.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void EdtIrARegistroPorNumeroKeyDown();
    
    void CbxIrARegistroPorNombreCloseUp(int index);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PULSAR UNA TECLA EN EL EDIT DE IR A VARIABLE.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void EdtIrAVariablePorNumeroKeyDown();
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SELECCIONAR UNA CELDA EN LA REJILLA.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void SgrRejillaSelectCell(const QModelIndex& index);
    void SgrRejillaSelectCellH(const int& index);
    void SgrRejillaSelectCellV(const int& index);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PULSAR ALT + UNA TECLA SOBRE LA REJILLA PRINCIPAL.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void SgrRejillaKeyDownAR();
    void SgrRejillaKeyDownAL();
    void SgrRejillaKeyDownAU();
    void SgrRejillaKeyDownAD();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PULSAR SHIFT + UNA TECLA SOBRE LA REJILLA PRINCIPAL.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void SgrRejillaKeyDownSR();
    void SgrRejillaKeyDownSL();
    void SgrRejillaKeyDownSU();
    void SgrRejillaKeyDownSD();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// HACER DOBLE CLICK SOBRE LA REJILLA DE VARIABLE.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void SgrRejillaVariableDblClick(const QModelIndex& index);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DOBLE CLICK SOBRE LA REJILLA PRINCIPAL.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void SgrRejillaDblClick(const QModelIndex& index);
    void ButAceptarCambiarMicrodatoClick();

    void ButCancelarCambiarMicrodatoClick();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// HACER DOBLE CLICK SOBRE LA REJILLA DE REGISTRO.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void SgrRejillaRegistroDonanteDblClick(const QModelIndex& index);
    void ButAplicarIrAVariableClick();
    void ButCancelarIrAVariableClick();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAMBIAR EL DESPLAZADOR DE REGISTROS DONANTES.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void UpdRegistroDonanteClick_sig();
    void UpdRegistroDonanteClick_ant();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PINCHAR LA OPCION DE MENU DE SALVAR MICRODATOS A FICHERO.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void MitSalvarMicrodatosFicheroClick();
    void VisualizarMenu(const QModelIndex& );
    void VisualizarInforRegIncorrecto(const int& );
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PINCHAR LA OPCION DE MENU DE SALVAR MICRODATOS A BBDD.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void MitSalvarMicrodatosBBDDClick();
    void ButAceptarEntradaDatosClick();

    void ButCancelarEntradaDatosClick();

    void MitAumentarColumnasClick();

    void MitDisminuirColumnasClick();

    void VisualizarRegCloseUp(int index);
    void ButAceptarPedirExpresionClick();
    void ButCancelarPedirExpresionClick();

private:

  TFmeTest *FmeTestAsociado;
  TFmeRangos *FmeRangosAsociados;
  TFmeEdits *FmeEditsAsociados;
  TFmeMicroDatos *FmeMicroDatosAsociados;
  TFmeVariables *FmeVariablesAsociadas;
  TFrmCambiarMicrodato *FrmCambiarMicrodato;
  TFrmIrAVariable *FrmIrAVariable;
  TFrmOpciones *FrmOpciones;
  TFrmEntradaDatos *FrmEntradaDatos;
  QSqlQuery *query5;
  bool Oracle;
  bool Xml;
  QString NombreBaseDatos;
  QString Name;
  unsigned NumEdits;
  unsigned NumVariables;
  unsigned NumRegistros;
  QSet<unsigned> *VectorVariablesAImputarExtendidoLargo;   // vbles a imputar extendidas largas imputables
  QSet<unsigned> *VectorVariablesAImputarExtendido;        // vbles a imputar extendidas cortas imputables
  QSet<unsigned> *VectorVariablesAImputarEdits;            // vbles de edits a imputar imputables
  QSet<unsigned> *VectorVariablesAImputarRango;            // vbles de rango a imputar imputables
  QSet<unsigned> *VectorVariablesAImputarExtendidoLargoAux; // vbles a imputar extendidas largas
  QSet<unsigned> *VectorVariablesAImputarExtendidoAux;      // vbles a imputar extendidas cortas
  QSet<unsigned> *VectorVariablesAImputarEditsAux;          // vbles de edits a imputar
  QSet<unsigned> *VectorVariablesAImputarRangoAux;          // vbles de rango a imputar
  unsigned *NumVariablesImputadas;
  unsigned *NumRegistrosImputados;
  TipoRegistroDonante **MatrizRegistrosDonantes;
  double **MatrizMicroDatos;
  QString **MatrizMicroDatosS;
  QString **MatrizMicroDatosSelec;
  QStringList listaH;
  QStringList listaV;
  QStringList listaVSelec;
  QStringList *ListaIds;
  bool **MatrizImputacion;
  bool Cargado;
  QSet<unsigned> ConjuntoRegistrosDonantes;
  QSet<unsigned> ConjuntoRegistrosExcluidos;
  QSet<unsigned> ConjuntoRegistrosIncorrectos;
  QSet<unsigned> ConjuntoRegistrosWarning;
  QSet<unsigned> *GrafoVariables;
  QList<TipoNodoCC> *ComponentesConexas;
  unsigned NumRegistrosDonantes;
  unsigned NumRegistrosExcluidos;
  unsigned NumRegistrosCorrectos;
  unsigned NumRegistrosIncorrectos;
  unsigned NumRegistrosWarning;
  unsigned NumRegistrosACorregir;
  unsigned NumRegistrosSelec;
  double PorcentajeRegistrosDonantes;
  double PorcentajeRegistrosExcluidos;
  double PorcentajeRegistrosCorrectos;
  double PorcentajeRegistrosIncorrectos;
  double PorcentajeRegistrosWarning;
  double PorcentajeRegistrosACorregir;
  QTime InstanteComienzo;
  QTime InstanteFinalizacion;
  TipoPesoVariable *VectorPesosVariables;
  TTipoVariableAImputar **MatrizTiposVariablesAImputar;
  unsigned *VectorMapeadoImputacionRegistros;
  unsigned NumRegistrosAImputar;
  double PromedioVariablesImputadasTotal, PromedioVariablesImputadasSinWarning, PromedioErroresRango, PromedioErroresEdits, PromedioErroresTotal, PromedioSizeCompConexas, PromedioDistancias;
  unsigned NumVariablesImputadasTotal, NumVariablesImputadasWarning, NumErroresRango, NumErroresEdits, NumErroresTotal, SizeCompConexas, SumDistancias;
  unsigned NRD; // numero de registros donantes

  QTextEdit *MemLogs;
  int posicion;
  TablaModelI *model;
  TablaModelInfoR *model2;
  QStringList listaH2;
  QStringList listaV2;
  QString *VectorDatosV;
  TablaModelInfoR *model3;
  QStringList listaH3;
  QStringList listaV3;
  QString *VectorDatosR;
  bool *ImputacionVar;  // indicara si ha imputado las variables numericas de forma incorrecta en SustituirImputacionVariablesNumericas()
  bool PermImputacManual;   // indica si se permite realizar imputacion manual, si se han resuelto las estadisticas no lo permite
  bool *ImpManualIncorrecto;  // indica si se ha realizado imputacion manual de un registro incorrecto
  bool *ImpManualCorrecto;  // indica si se ha realizado imputacion manual de un registro correcto
  bool Excel;
  TFrmPedirExpresion *wpedexp;  

};

#endif // IMPUTACION_H
